﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using TipTepOpenNI;
using System.Threading;
using TipTepCore;
using TipTepLogger;

namespace TipTep.Recorder
{
    public partial class frmMain : Form
    {        
        TipTepHandSkeletonnet.HandSkeleton handSkeleton;
        BackgroundWorker skeletonWorker = new BackgroundWorker();        
        bool snapshot = false;
        int pruning = 0;

        public frmMain()
        {
            InitializeComponent();
        }

        #region Form events

        /// <summary>
        /// Initialization
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_Load(object sender, EventArgs e)            
        {            
            pictureBox1.BackgroundImageLayout = ImageLayout.Stretch;
            skeletonWorker.WorkerReportsProgress = true;
            skeletonWorker.WorkerSupportsCancellation = true;
            skeletonWorker.ProgressChanged += new ProgressChangedEventHandler(skeletonWorker_ProgressChanged);
            skeletonWorker.DoWork += new DoWorkEventHandler(skeletonWorker_DoWork);            
        }

        /// <summary>
        /// Start sensor depth image streaming
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonStart_Click(object sender, EventArgs e)
        {
            buttonStart.Enabled = false;
            numericUpDownPruning.Enabled = false;
            skeletonWorker.RunWorkerAsync();
            pruning = Convert.ToInt32(numericUpDownPruning.Value);
        }

        /// <summary>
        /// Shutdown sensor before closing form
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (handSkeleton != null)
            {
                handSkeleton.Stop();                
            }
        }

        #endregion

        /// <summary>
        /// Generate hand skeleton background
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void skeletonWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                handSkeleton = new TipTepHandSkeletonnet.HandSkeleton(pruning, 100);
                handSkeleton.SkeletonUpdate += new TipTepHandSkeletonnet.HandSkeleton.DelegateSkeletonUpdate(handSkeleton_SkeletonUpdate);
                handSkeleton.Start();
            }
            catch (Exception ex)
            {
                Log.Write("skeletonWorker_DoWork", ex.Message);
            }
        }

        /// <summary>
        /// Draw skeleton and depth image
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void skeletonWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.ProgressPercentage == 100)
            {                
                this.Close();
            }
            else
            {
                Bitmap depthImage = e.UserState as Bitmap;
                if (depthImage != null)
                {
                    pictureBox1.BackgroundImage = depthImage;
                }
            }
        }
      
        /// <summary>
        /// Analyse arrived image and skeleton
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="rgb">RGB image</param>
        /// <param name="depth">Depth image</param>
        /// <param name="handPoints">Hand points</param>
        /// <param name="skeleton">Hand skeleton</param>
        /// <param name="handRectangle">Hand surrounding rectnalge</param>
        void handSkeleton_SkeletonUpdate(object sender, Frame rgb, Frame depth, Point3D[] handPoints, Skeleton3D skeleton, RectangleF handRectangle)
        {            

            if (depth != null)
            {
                #region Depth image and skeleton rendering

                Bitmap depthImage = TipTep.ImageAnalyzer.ImageHelper.Get2DImage(depth.GetData(), depth.GetWidth(), depth.GetHeight(), ImageAnalyzer.ImageTransferMode2D.OpenNIHistogram);
                Graphics gr = Graphics.FromImage(depthImage);
                if (handPoints != null && handPoints.Length > 0)
                {
                    foreach (Point3D p in handPoints)
                    {
                        gr.DrawArc(Pens.Red, p.X - 5, p.Y - 5, 10, 10, 0, 360);
                    }
                }
                if (handRectangle != RectangleF.Empty)
                {
                    gr.DrawRectangle(Pens.Red, handRectangle.X, handRectangle.Y, handRectangle.Width, handRectangle.Height);
                }
                if (skeleton != null && skeleton.Lines != null)
                {
                    for (int k = 0; k < skeleton.Lines.Count; k++)
                    {
                        gr.DrawLine(Pens.Red, skeleton.Lines[k].Start.X, skeleton.Lines[k].Start.Y, skeleton.Lines[k].End.X, skeleton.Lines[k].End.Y);
                    }                   
                }
                skeletonWorker.ReportProgress(0, depthImage);

                #endregion                

                if (snapshot && handPoints.Length > 0)
                {
                    snapshot = false;
                    Recorder recorder = new Recorder(depth, handPoints[0], handRectangle, skeleton);
                    BackgroundWorker asynchRecorder = new BackgroundWorker();
                    asynchRecorder.DoWork += new DoWorkEventHandler(asynchRecorder_DoWork);
                    asynchRecorder.RunWorkerAsync(recorder);
                }
            }
        }

        #region Recording
                    
        /// <summary>
        /// Take a snapshot of hand image
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonSnapshot_Click(object sender, EventArgs e)
        {
            snapshot = true;
        }

        /// <summary>
        /// Record depth image and hand data to xml file
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void asynchRecorder_DoWork(object sender, DoWorkEventArgs e)
        {
            Recorder recorder = e.Argument as Recorder;
            if (recorder != null)
            {
                recorder.RecordHandData();
            }
        }

        #endregion
      
    }
}
